<script setup lang="ts">
import { Plus } from "@element-plus/icons-vue"
import Table from "@/components/Table/index.vue"
import { propsList } from "./config"
import Modal from "@/components/modal/index.vue"
import { ref, Ref, reactive, onMounted } from "vue"
import { type FormInstance, FormRules, ElMessage } from "element-plus"
import { type IRoleListData, IRoleTreeData, IAddOrEditRoleParams } from "@/api/system/types"
import {
  getRoleListApi,
  getRoleNodeApi,
  getRoleAllNodeApi,
  delRoleApi,
  addRoleApi,
  editRoleApi
} from "@/api/system/index"

interface IRoleForm {
  id: number
  /** 角色名字 **/
  role_name: string
  /** 角色描述 **/
  role_remarks: string
  /** 权限管理 **/
  role_permission: number[]
}

const defaultProps = {
  children: "children",
  label: "node_title",
  disabled: "disabled"
}

const roleForm = reactive<IRoleForm>({
  id: 0,
  role_name: "",
  role_remarks: "",
  role_permission: []
})
const roleFormRef = ref<FormInstance>()
const roleRule = ref<FormRules<Partial<IRoleForm>>>({
  role_name: [{ required: true, message: "请输入角色名称" }],
  role_permission: [{ required: true, message: "请选择权限管理" }]
})

const permissionData = ref<IRoleTreeData[]>([])
const allPermission = ref<IRoleTreeData[]>([])

const tableData = ref<IRoleListData[]>([])
const searcherParams = reactive({
  data_sum: 0,
  page_index: 1,
  page_size: 10
})

const hasPermissionData = ref<number[]>([])
const roleTitle = ref("新增角色")
const isDetail = ref<boolean>(false)
const isEdit = ref<boolean>(false)
const addRoleModalRef: Ref<typeof Modal | null> = ref(null)
const delModalRef: Ref<typeof Modal | null> = ref(null)

const handleCloseRole = () => {
  roleFormRef.value?.resetFields()
  isEdit.value = false
  ;(addRoleModalRef as Ref<typeof Modal>).value.closeModal()
}

const resetData = () => {
  roleForm.role_name = ""
  roleForm.role_remarks = ""
  roleForm.role_permission = []
}

const handleAdd = () => {
  resetData()
  isDetail.value = false
  roleTitle.value = "新增角色"
  hasPermissionData.value = []
  permissionData.value = allPermission.value
  ;(addRoleModalRef as Ref<typeof Modal>).value.showModal()
}

// 权限选中
const handleCheck = (data: any, checkData: any) => {
  roleForm.role_permission = checkData.checkedKeys
}

// 编辑新增角色确定handle
const handleRoleConfirm = async () => {
  const { role_name, role_remarks, role_permission, id } = roleForm

  if (isEdit.value) {
    if (!hasPermissionData.value.length) {
      return ElMessage.error("请选择权限")
    }
  } else {
    if (!role_permission.length) {
      return ElMessage.error("请选择权限")
    }
  }

  const params: IAddOrEditRoleParams = {
    role_name,
    role_remarks,
    node_id: role_permission
  }

  if (isEdit.value) {
    params.role_id = id
  }

  const res = isEdit.value ? await editRoleApi(params) : await addRoleApi(params)
  const { result, return_message } = res
  if (result === 200) {
    ElMessage.success(isEdit.value ? "编辑成功" : "新增成功")
    resetData()
    getRoleList()
    handleCloseRole()
  } else {
    ElMessage.error(return_message)
  }
}

// 详情
const handleDetail = async (row: IRoleListData) => {
  try {
    const params = {
      role_id: row.id
    }
    const res = await getRoleNodeApi(params)
    const { result, return_message, data } = res
    if (result === 200) {
      hasPermissionData.value = data
    } else {
      ElMessage.error(return_message)
    }

    const filteredTree = allPermission.value
      .map((root) => filterTree(root, hasPermissionData.value))
      .filter((root) => root !== null) as any

    permissionData.value = filteredTree

    Object.assign(roleForm, row)
    roleTitle.value = "角色详情"
    isDetail.value = true
    ;(addRoleModalRef as Ref<typeof Modal>).value.showModal()
  } catch (error) {
    console.info(error)
  }
}

// 编辑
const handleEdit = async (row: IRoleListData) => {
  const params = {
    role_id: row.id
  }
  const res = await getRoleNodeApi(params)
  const { result, return_message, data } = res
  if (result === 200) {
    hasPermissionData.value = data
    permissionData.value = allPermission.value
  } else {
    ElMessage.error(return_message)
  }

  Object.assign(roleForm, row)
  roleTitle.value = "编辑角色"
  isDetail.value = false
  isEdit.value = true
  ;(addRoleModalRef as Ref<typeof Modal>).value.showModal()
}

// 关闭删除弹窗
const handleCloseDel = () => {
  ;(delModalRef as Ref<typeof Modal>).value.closeModal()
}

// 确定删除
const handleConfirmDel = async () => {
  const params = {
    role_id: roleForm.id
  }
  const res = await delRoleApi(params)
  const { result, return_message } = res
  if (result === 200) {
    ElMessage.success("删除成功")
    getRoleList()
    handleCloseDel()
  } else {
    ElMessage.error(return_message)
  }
}

// 删除
const handleDel = (row: IRoleListData) => {
  Object.assign(roleForm, row)
  ;(delModalRef as Ref<typeof Modal>).value.showModal()
}

// 获取列表数据
const getRoleList = async () => {
  const { page_size, page_index } = searcherParams
  const params = {
    page_index,
    page_size
  }
  const res = await getRoleListApi(params)
  const { data, result, return_message } = res

  if (result === 200) {
    const { page_index, page_size, data_sum } = data
    searcherParams.data_sum = data_sum
    searcherParams.page_index = page_index
    searcherParams.page_size = page_size
    tableData.value = data.data
  } else {
    ElMessage.error(return_message)
  }
}

const handleChangePage = (page: number) => {
  searcherParams.page_index = page
  getRoleList()
}

const handleChangeSize = (size: number) => {
  searcherParams.page_size = size
  getRoleList()
}

// 获取权限数据
const getRoleAllNode = async () => {
  try {
    const res = await getRoleAllNodeApi()
    const { result, return_message, data } = res
    if (result === 200) {
      disabledPermission(data)
      permissionData.value = data
      allPermission.value = data
    } else {
      ElMessage.error(return_message)
    }
  } catch (error) {
    console.info(error)
  }
}

// 禁用权限
const disabledPermission = (data: IRoleTreeData[]) => {
  const disabledData = data.find((item) => item.node_name === "System") as IRoleTreeData

  const addProps = (target: IRoleTreeData) => {
    target.disabled = true

    if (target.children) {
      target.children.forEach((item) => addProps(item))
    }
  }

  addProps(disabledData)
}

const filterTree = (tree: IRoleTreeData, ids: number[]): IRoleTreeData | null => {
  // 如果当前节点的 id 在 ids 数组中，则返回当前节点的副本（包括其子节点）
  if (ids.includes(tree.id)) {
    const treeObj = {
      ...tree
    }

    if (tree.children) {
      treeObj.children = tree.children.map((child) => filterTree(child, ids)).filter((child) => child !== null)
    }
    return treeObj
  } else {
    // 否则递归遍历当前节点的子节点
    if (tree.children) {
      const filteredChildren = tree.children.map((child) => filterTree(child, ids)).filter((child) => child !== null)
      return filteredChildren.length > 0 ? { ...tree, children: filteredChildren } : null
    } else {
      return null
    }
  }
}

onMounted(() => {
  getRoleList()
  getRoleAllNode()
})
</script>

<template>
  <div>
    <header flex justify-between mb-15px>
      <span>后台角色配置</span>
      <el-button type="primary" @click="handleAdd" :icon="Plus" class="bg-#387af6!">添加角色</el-button>
    </header>

    <!-- 表格 -->
    <div p-5px bg-white>
      <Table
        :total="searcherParams.data_sum"
        :index="true"
        header-align="center"
        :data="tableData"
        :propsList="propsList"
        :is-border="true"
        @change-page="handleChangePage"
        @change-size="handleChangeSize"
      >
        <template #handler="{ row }">
          <div flex justify-around>
            <span cursor-pointer @click="handleDetail(row)" class="text-#1890FF">详情</span>
            <span v-if="!row.role_default" cursor-pointer @click="handleEdit(row)" class="text-#1890FF">编辑</span>
            <span v-if="!row.role_default" cursor-pointer @click="handleDel(row)" class="text-#FF4C4C">删除</span>
          </div>
        </template>
      </Table>
    </div>

    <Modal ref="addRoleModalRef" width="620px" :title="roleTitle" @close="handleCloseRole">
      <template #content>
        <div>
          <el-form :model="roleForm" ref="roleFormRef" :rules="roleRule" style="max-width: 660px">
            <el-form-item class="mb-24px!" label="角色名称：" label-width="105px" prop="role_name">
              <span v-if="isDetail">{{ roleForm.role_name }}</span>
              <el-input v-else placeholder="请输入角色名称" v-model="roleForm.role_name" clearable />
            </el-form-item>
            <el-form-item class="mb-24px!" label="角色描述：" label-width="105px" prop="role_remarks">
              <span v-if="isDetail">{{ roleForm.role_remarks }}</span>

              <el-input
                v-else
                clearable
                type="textarea"
                maxlength="100"
                show-word-limit
                placeholder="请输入角色描述"
                v-model="roleForm.role_remarks"
              />
            </el-form-item>

            <el-form-item class="mb-24px!" label="权限管理：" label-width="105px" prop="role_permission">
              <div w-full>
                <el-tree
                  @check="handleCheck"
                  :default-checked-keys="hasPermissionData"
                  default-expand-all
                  class="bg-#f7f9fb! h-250px overflow-y-auto scroll-smooth"
                  style="max-width: 600px"
                  :data="permissionData"
                  :show-checkbox="!isDetail"
                  node-key="id"
                  :props="defaultProps"
                />
              </div>
            </el-form-item>
          </el-form>
        </div>
      </template>

      <template #footer>
        <div pr-20px>
          <el-button class="w-105px!" @click="handleCloseRole">{{ isDetail ? "关闭" : "取消" }}</el-button>
          <el-button v-if="!isDetail" class="w-105px! bg-#387af6!" type="primary" @click="handleRoleConfirm">
            确定
          </el-button>
        </div>
      </template>
    </Modal>

    <!-- 删除分区 -->
    <Modal ref="delModalRef" title="删除角色" width="520" @close="handleCloseDel">
      <template #content>
        <div flex flex-col>
          <div flex items-center mb-10px>
            <SvgIcon name="warning" class="w-20px! h-20px!" />
            <span ml-15px pl-5px h-35px leading-40px text-black text-18px> 确认删除该角色吗？ </span>
          </div>

          <div mt-15px>
            <el-row border-1px border-solid class="border-#dfe1e3">
              <el-col :span="5">
                <div flex items-center>
                  <span text-center p-15px w-100px class="bg-#ebedef">角色名称</span>
                </div>
              </el-col>
              <el-col :span="19">
                <div bg-white h-full flex justify-center items-center>
                  <span text-center truncate w-378px>
                    {{ roleForm.role_name }}
                  </span>
                </div>
              </el-col>
            </el-row>
            <el-row border-t-none border-1px border-solid class="border-#dfe1e3">
              <el-col :span="5">
                <div flex items-center>
                  <span text-center p-15px w-100px class="bg-#ebedef">角色描述</span>
                </div>
              </el-col>
              <el-col :span="19">
                <div bg-white h-full flex justify-center items-center truncate w-378px>
                  <span text-center truncate w-378px>
                    {{ roleForm.role_remarks }}
                  </span>
                </div>
              </el-col>
            </el-row>
          </div>
        </div>
      </template>

      <template #footer>
        <div pr-20px>
          <el-button class="w-105px!" @click="handleCloseDel">取消</el-button>
          <el-button class="w-105px! bg-#387af6!" type="primary" @click="handleConfirmDel"> 确定 </el-button>
        </div>
      </template>
    </Modal>
  </div>
</template>

<style lang="scss" scoped>
:deep(.el-form-item) {
  margin-bottom: 0px;
}

:deep(.el-dialog) {
  background: #f7f9fb;
  padding-left: 0;
  padding-right: 0;
  padding-top: 0;
  border-radius: 5px;

  .el-dialog__body {
    padding: 20px;
  }
}

/* 隐藏垂直滚动条 */
::-webkit-scrollbar {
  width: 4px;
  background-color: #fff;
}

/* 滚动条轨道 */
::-webkit-scrollbar-track {
  background-color: #f7f9fb;
}

/* 滚动条滑块 */
::-webkit-scrollbar-thumb {
  background-color: #c6cbd0;
  border-radius: 4px;
}

/* 鼠标悬停在滚动条上时的样式 */
::-webkit-scrollbar-thumb:hover {
  background-color: #c6cbd0;
}

// 兼容火狐浏览器
.scroll_container {
  scrollbar-width: thin; //滚动条变细，为none时隐藏滚动条
  scrollbar-color: #c6cbd0 #fff;
}
</style>
